#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""

from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import

智能错误提示系统
针对不同发行版常见问题提供排查建议和解决方案
"""

import os
import sys

# Python 2/3 兼容性处理
if sys.version_info[0] == 2:
    string_types = basestring
    text_type = unicode
    def iteritems(d):
        return d.iteritems()
    def itervalues(d):
        return d.itervalues()
else:
    string_types = str
    text_type = str
    def iteritems(d):
        return d.items()
    def itervalues(d):
        return d.values()
import subprocess
import re
from core.utils import color_green, color_red, color_yellow, color_blue, run_command_compat
from core.distro_detection import detect_linux_distro




class SmartErrorHandler:
    """智能错误处理器"""
    
    def __init__(self):
        self.distro_info = detect_linux_distro()
        self.error_patterns = self._load_error_patterns()
        self.distro_specific_solutions = self._load_distro_solutions()
        
    def _load_error_patterns(self):
        """加载错误模式"""
        return {
            'ssh_key_errors': {
                'permission_denied': [
                    r'permission denied',
                    r'access denied',
                    r'operation not permitted'
                ],
                'file_not_found': [
                    r'no such file or directory',
                    r'file not found',
                    r'cannot access'
                ],
                'ssh_config_error': [
                    r'publickey authentication failed',
                    r'key not accepted',
                    r'authentication refused'
                ]
            },
            'systemd_errors': {
                'service_failed': [
                    r'failed to start',
                    r'service failed',
                    r'unit failed'
                ],
                'permission_error': [
                    r'permission denied',
                    r'access denied',
                    r'operation not permitted'
                ],
                'selinux_error': [
                    r'selinux',
                    r'security context',
                    r'avc denied'
                ],
                'apparmor_error': [
                    r'apparmor',
                    r'profile',
                    r'denied'
                ]
            },
            'crontab_errors': {
                'cron_not_running': [
                    r'cron.*not.*running',
                    r'crond.*inactive',
                    r'crontab.*service.*down'
                ],
                'permission_error': [
                    r'permission denied',
                    r'access denied',
                    r'not allowed'
                ],
                'syntax_error': [
                    r'syntax error',
                    r'bad minute',
                    r'bad hour',
                    r'invalid crontab'
                ]
            },
            'firewall_errors': {
                'port_blocked': [
                    r'connection refused',
                    r'port.*blocked',
                    r'firewall.*blocking'
                ],
                'iptables_error': [
                    r'iptables.*error',
                    r'chain.*not.*found',
                    r'target.*not.*found'
                ]
            }
        }
    
    def _load_distro_solutions(self):
        """加载发行版特定解决方案"""
        return {
            'ubuntu': {
                'ssh_key_errors': {
                    'permission_denied': [
                        "检查.ssh目录权限: chmod 700 ~/.ssh",
                        "检查authorized_keys权限: chmod 600 ~/.ssh/authorized_keys",
                        "检查AppArmor状态: sudo aa-status",
                        "检查SSH配置: sudo nano /etc/ssh/sshd_config",
                        "重启SSH服务: sudo systemctl restart ssh"
                    ],
                    'ssh_config_error': [
                        "启用公钥认证: PubkeyAuthentication yes",
                        "检查AuthorizedKeysFile配置",
                        "检查用户主目录权限: chmod 755 ~",
                        "查看SSH日志: sudo journalctl -u ssh"
                    ]
                },
                'systemd_errors': {
                    'service_failed': [
                        "检查服务文件语法: systemd-analyze verify service.service",
                        "查看详细错误: sudo journalctl -u service-name",
                        "检查AppArmor限制: sudo aa-status",
                        "重新加载systemd: sudo systemctl daemon-reload"
                    ],
                    'apparmor_error': [
                        "检查AppArmor配置: sudo aa-status",
                        "临时禁用AppArmor: sudo aa-complain /path/to/profile",
                        "查看AppArmor日志: sudo dmesg | grep apparmor",
                        "编辑AppArmor配置: sudo aa-logprof"
                    ]
                },
                'crontab_errors': {
                    'cron_not_running': [
                        "启动cron服务: sudo systemctl start cron",
                        "启用cron服务: sudo systemctl enable cron",
                        "检查cron状态: sudo systemctl status cron",
                        "查看cron日志: sudo journalctl -u cron"
                    ]
                }
            },
            'centos': {
                'ssh_key_errors': {
                    'permission_denied': [
                        "检查.ssh目录权限: chmod 700 ~/.ssh",
                        "检查authorized_keys权限: chmod 600 ~/.ssh/authorized_keys",
                        "检查SELinux状态: getenforce",
                        "设置SELinux上下文: restorecon -R ~/.ssh",
                        "重启SSH服务: sudo systemctl restart sshd"
                    ],
                    'ssh_config_error': [
                        "启用公钥认证: PubkeyAuthentication yes",
                        "检查SELinux布尔值: getsebool -a | grep ssh",
                        "允许SSH密钥认证: setsebool -P ssh_keysign on",
                        "查看SSH日志: sudo journalctl -u sshd"
                    ]
                },
                'systemd_errors': {
                    'service_failed': [
                        "检查服务文件语法: systemd-analyze verify service.service",
                        "查看详细错误: sudo journalctl -u service-name",
                        "检查SELinux限制: sudo ausearch -m avc -ts recent",
                        "重新加载systemd: sudo systemctl daemon-reload"
                    ],
                    'selinux_error': [
                        "检查SELinux状态: getenforce",
                        "查看SELinux日志: sudo ausearch -m avc -ts recent",
                        "临时禁用SELinux: sudo setenforce 0",
                        "生成SELinux策略: sudo audit2allow -a",
                        "设置正确的SELinux上下文: sudo restorecon -R /path"
                    ]
                },
                'crontab_errors': {
                    'cron_not_running': [
                        "启动crond服务: sudo systemctl start crond",
                        "启用crond服务: sudo systemctl enable crond",
                        "检查crond状态: sudo systemctl status crond",
                        "查看cron日志: sudo journalctl -u crond"
                    ]
                }
            },
            'fedora': {
                'ssh_key_errors': {
                    'permission_denied': [
                        "检查.ssh目录权限: chmod 700 ~/.ssh",
                        "检查authorized_keys权限: chmod 600 ~/.ssh/authorized_keys",
                        "检查SELinux状态: getenforce",
                        "设置SELinux上下文: restorecon -R ~/.ssh",
                        "重启SSH服务: sudo systemctl restart sshd"
                    ]
                },
                'systemd_errors': {
                    'selinux_error': [
                        "检查SELinux状态: getenforce",
                        "查看SELinux日志: sudo journalctl | grep -i selinux",
                        "使用audit2allow生成策略: sudo audit2allow -a",
                        "临时设置为宽松模式: sudo setenforce 0"
                    ]
                }
            },
            'debian': {
                'ssh_key_errors': {
                    'permission_denied': [
                        "检查.ssh目录权限: chmod 700 ~/.ssh",
                        "检查authorized_keys权限: chmod 600 ~/.ssh/authorized_keys",
                        "重启SSH服务: sudo systemctl restart ssh",
                        "查看SSH日志: sudo journalctl -u ssh"
                    ]
                },
                'crontab_errors': {
                    'cron_not_running': [
                        "启动cron服务: sudo systemctl start cron",
                        "启用cron服务: sudo systemctl enable cron",
                        "检查cron状态: sudo systemctl status cron"
                    ]
                }
            },
            'suse': {
                'ssh_key_errors': {
                    'permission_denied': [
                        "检查.ssh目录权限: chmod 700 ~/.ssh",
                        "检查authorized_keys权限: chmod 600 ~/.ssh/authorized_keys",
                        "重启SSH服务: sudo systemctl restart sshd",
                        "查看SSH日志: sudo journalctl -u sshd"
                    ]
                },
                'crontab_errors': {
                    'cron_not_running': [
                        "启动cron服务: sudo systemctl start cron",
                        "启用cron服务: sudo systemctl enable cron",
                        "检查cron状态: sudo systemctl status cron"
                    ]
                }
            }
        }
    
    def analyze_error(self, error_message, error_context='general'):
        """分析错误并提供解决方案"""
        if not error_message:
            return None
        
        error_message_lower = error_message.lower()
        
        # 确定错误类型
        error_type = self._classify_error(error_message_lower, error_context)
        
        if not error_type:
            return self._get_generic_solutions(error_context)
        
        # 获取发行版特定解决方案
        distro_name = self._get_distro_name()
        solutions = self._get_distro_specific_solutions(distro_name, error_context, error_type)
        
        # 如果没有发行版特定解决方案，使用通用解决方案
        if not solutions:
            solutions = self._get_generic_solutions(error_context, error_type)
        
        return {
            'error_type': error_type,
            'error_context': error_context,
            'distro': distro_name,
            'solutions': solutions,
            'additional_checks': self._get_additional_checks(distro_name, error_context)
        }
    
    def _classify_error(self, error_message, context):
        """分类错误类型"""
        if context not in self.error_patterns:
            return None
        
        patterns = self.error_patterns[context]
        
        for error_type, pattern_list in patterns.items():
            for pattern in pattern_list:
                if re.search(pattern, error_message, re.IGNORECASE):
                    return error_type
        
        return None
    
    def _get_distro_name(self):
        """获取发行版名称"""
        if not self.distro_info:
            return 'generic'
        
        distro_name = self.distro_info.get('name', '').lower()
        
        # 映射到支持的发行版
        if 'ubuntu' in distro_name:
            return 'ubuntu'
        elif 'centos' in distro_name or 'rhel' in distro_name:
            return 'centos'
        elif 'fedora' in distro_name:
            return 'fedora'
        elif 'debian' in distro_name:
            return 'debian'
        elif 'suse' in distro_name or 'opensuse' in distro_name:
            return 'suse'
        else:
            return 'generic'
    
    def _get_distro_specific_solutions(self, distro_name, context, error_type):
        """获取发行版特定解决方案"""
        if distro_name not in self.distro_specific_solutions:
            return []
        
        distro_solutions = self.distro_specific_solutions[distro_name]
        
        if context not in distro_solutions:
            return []
        
        context_solutions = distro_solutions[context]
        
        if error_type not in context_solutions:
            return []
        
        return context_solutions[error_type]
    
    def _get_generic_solutions(self, context, error_type=None):
        """获取通用解决方案"""
        generic_solutions = {
            'ssh_key_errors': [
                "检查SSH服务状态: systemctl status ssh/sshd",
                "检查SSH配置文件: /etc/ssh/sshd_config",
                "检查用户权限和文件权限",
                "查看系统日志: journalctl -xe"
            ],
            'systemd_errors': [
                "检查服务文件语法",
                "查看详细错误日志: journalctl -u service-name",
                "重新加载systemd配置: systemctl daemon-reload",
                "检查文件权限和路径"
            ],
            'crontab_errors': [
                "检查cron服务状态: systemctl status cron/crond",
                "验证crontab语法",
                "检查用户权限",
                "查看cron日志"
            ],
            'firewall_errors': [
                "检查防火墙状态",
                "检查端口是否开放",
                "查看iptables规则",
                "检查网络连接"
            ]
        }
        
        return generic_solutions.get(context, ["检查系统日志", "验证配置文件", "检查权限设置"])
    
    def _get_additional_checks(self, distro_name, context):
        """获取额外检查项"""
        additional_checks = {
            'ubuntu': {
                'ssh_key_errors': [
                    "检查AppArmor状态: sudo aa-status",
                    "查看AppArmor日志: sudo dmesg | grep apparmor"
                ],
                'systemd_errors': [
                    "检查AppArmor限制",
                    "验证服务依赖关系"
                ]
            },
            'centos': {
                'ssh_key_errors': [
                    "检查SELinux状态: getenforce",
                    "查看SELinux日志: ausearch -m avc -ts recent"
                ],
                'systemd_errors': [
                    "检查SELinux上下文",
                    "验证防火墙规则"
                ]
            },
            'fedora': {
                'ssh_key_errors': [
                    "检查SELinux状态: getenforce",
                    "查看SELinux日志"
                ],
                'systemd_errors': [
                    "检查SELinux策略",
                    "验证systemd版本兼容性"
                ]
            }
        }
        
        return additional_checks.get(distro_name, {}).get(context, [])
    
    def provide_interactive_troubleshooting(self, error_message, error_context='general'):
        """提供交互式故障排除"""
        color_blue("=== 智能错误分析 ===")
        
        analysis = self.analyze_error(error_message, error_context)
        
        if not analysis:
            color_yellow("无法分析此错误，提供通用建议:")
            generic_solutions = self._get_generic_solutions(error_context)
            for i, solution in enumerate(generic_solutions, 1):
                color_yellow("{}. {}".format(i, solution))
            return
        
        color_green("错误类型: {}".format(analysis['error_type']))
        color_green("错误上下文: {}".format(analysis['error_context']))
        color_green("目标系统: {}".format(analysis['distro']))
        
        color_blue("\n建议解决方案:")
        for i, solution in enumerate(analysis['solutions'], 1):
            color_green("{}. {}".format(i, solution))
        
        if analysis['additional_checks']:
            color_blue("\n额外检查项:")
            for i, check in enumerate(analysis['additional_checks'], 1):
                color_yellow("{}. {}".format(i, check))
        
        # 提供自动修复选项
        self._offer_auto_fix(analysis)
    
    def _offer_auto_fix(self, analysis):
        """提供自动修复选项"""
        color_blue("\n自动修复选项:")
        
        auto_fixes = self._get_auto_fixes(analysis['distro'], analysis['error_context'], analysis['error_type'])
        
        if not auto_fixes:
            color_yellow("暂无可用的自动修复选项")
            return
        
        for i, fix in enumerate(auto_fixes, 1):
            color_green("{}. {}".format(i, fix['description']))
        
        try:
            choice = input("\n选择自动修复选项 (输入数字，0跳过): ").strip()
            
            if choice == '0':
                return
            
            choice_idx = int(choice) - 1
            if 0 <= choice_idx < len(auto_fixes):
                selected_fix = auto_fixes[choice_idx]
                color_blue("执行修复: {}".format(selected_fix['description']))
                
                success = self._execute_auto_fix(selected_fix)
                if success:
                    color_green("✓ 自动修复完成")
                else:
                    color_red("✗ 自动修复失败")
            else:
                color_yellow("无效选择")
                
        except (ValueError, KeyboardInterrupt):
            color_yellow("跳过自动修复")
    
    def _get_auto_fixes(self, distro_name, context, error_type):
        """获取自动修复选项"""
        auto_fixes = {
            'ubuntu': {
                'ssh_key_errors': {
                    'permission_denied': [
                        {
                            'description': '修复SSH目录和文件权限',
                            'commands': [
                                'chmod 700 ~/.ssh',
                                'chmod 600 ~/.ssh/authorized_keys',
                                'chown $USER:$USER ~/.ssh ~/.ssh/authorized_keys'
                            ]
                        }
                    ]
                },
                'systemd_errors': {
                    'service_failed': [
                        {
                            'description': '重新加载systemd并重启服务',
                            'commands': [
                                'systemctl daemon-reload'
                            ]
                        }
                    ]
                },
                'crontab_errors': {
                    'cron_not_running': [
                        {
                            'description': '启动并启用cron服务',
                            'commands': [
                                'systemctl start cron',
                                'systemctl enable cron'
                            ]
                        }
                    ]
                }
            },
            'centos': {
                'ssh_key_errors': {
                    'permission_denied': [
                        {
                            'description': '修复SSH权限并设置SELinux上下文',
                            'commands': [
                                'chmod 700 ~/.ssh',
                                'chmod 600 ~/.ssh/authorized_keys',
                                'restorecon -R ~/.ssh'
                            ]
                        }
                    ]
                },
                'crontab_errors': {
                    'cron_not_running': [
                        {
                            'description': '启动并启用crond服务',
                            'commands': [
                                'systemctl start crond',
                                'systemctl enable crond'
                            ]
                        }
                    ]
                }
            }
        }
        
        return auto_fixes.get(distro_name, {}).get(context, {}).get(error_type, [])
    
    def _execute_auto_fix(self, fix):
        """执行自动修复"""
        try:
            for command in fix['commands']:
                color_blue("执行: {}".format(command))
                result = subprocess.run(command, shell=True, capture_output=True, text=True)
                
                if result.returncode != 0:
                    color_red("命令执行失败: {}".format(result.stderr))
                    return False
                else:
                    color_green(f"命令执行成功")
            
            return True
            
        except Exception as e:
            color_red("自动修复异常: {}".format(e))
            return False
    
    def generate_troubleshooting_report(self, errors_list):
        """生成故障排除报告"""
        report = {
            'system_info': self.distro_info,
            'timestamp': datetime.now().isoformat(),
            'errors_analyzed': len(errors_list),
            'analyses': []
        }
        
        for error_info in errors_list:
            error_message = error_info.get('message', '')
            error_context = error_info.get('context', 'general')
            
            analysis = self.analyze_error(error_message, error_context)
            if analysis:
                report['analyses'].append(analysis)
        
        return report

# 便捷函数
def quick_error_analysis(error_message, context='general'):
    """快速错误分析"""
    handler = SmartErrorHandler()
    handler.provide_interactive_troubleshooting(error_message, context)

if __name__ == "__main__":
    # 测试智能错误处理器
    color_blue("智能错误处理器测试")
    
    handler = SmartErrorHandler()
    
    # 测试SSH错误
    test_errors = [
        {
            'message': 'Permission denied (publickey)',
            'context': 'ssh_key_errors'
        },
        {
            'message': 'Failed to start service',
            'context': 'systemd_errors'
        },
        {
            'message': 'cron service not running',
            'context': 'crontab_errors'
        }
    ]
    
    for error in test_errors:
        print("\n{}".format('='*50))
        handler.provide_interactive_troubleshooting(error['message'], error['context'])